package store.pay;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import store.pay.icbc.IcbcB2cServerPayResultService;
import store.util.Constants;
import store.util.PayConfig;
import store.util.StringUtils;

public class NotifyServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
	private ApplicationContext ctx = null;
	
    public NotifyServlet() {
        super();
    }

	/**
	 * @see Servlet#init(ServletConfig)
	 */
	public void init(ServletConfig config) throws ServletException {
		 ctx =WebApplicationContextUtils.getWebApplicationContext(config.getServletContext());
	}

	/**
	 * 地址确认及生成。对于url connection需要带协议路径。而其他则是应用绝对路径
	 * @param request
	 * @param path 带协议头的绝对路径，或应用绝对路径。
	 * @return
	 */
	private String getPath(HttpServletRequest request, String path) {
		path += "";
		if (path.toLowerCase().startsWith("http://") || path.toLowerCase().startsWith("https://")) {
			return path;
		}
		String s = request.getRequestURL().toString().replace(request.getRequestURI(), "") + request.getContextPath();
		if (!path.startsWith("/")) {
			path = "/" + path;
		}
		
		return s + path;
	}
	
	/**
	 * @see HttpServlet#service(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void service(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		
		try {
			request.setCharacterEncoding("UTF-8");
			response.setContentType("text/html;charset=UTF-8");
			String pathInfo = request.getPathInfo();
			System.out.println(pathInfo);
			if (pathInfo.startsWith("/")) {
				pathInfo = pathInfo.substring(1);
			}
			
			String[] paths = null;
			// 不符合规则，forbidden
			if (null == (paths = pathInfo.split("/")) || paths.length < 1) {
				response.sendError(HttpServletResponse.SC_FORBIDDEN);
				return;
			}
			
			String bank = StringUtils.firstUpper(paths[0]);
			String serviceClazzName = bank
					+ (paths.length > 1 ? StringUtils.firstUpper(paths[1]) : "")
					+ (paths.length > 2 ? StringUtils.firstUpper(paths[2]) : "");

			PayResultService ps = new IcbcB2cServerPayResultService();
			// 获取支付结果对象
			PayResultObject pro = ps.payResultObject(request);
			
			Map<String, Object> params = new HashMap<String, Object>();
			
			params.put(PayConfig.PAY_RESULT_DO_PARAM_ORDERID, pro.orderId());
			params.put(PayConfig.PAY_RESULT_DO_PARAM_ORDERAMOUNT, pro.payAmount());
			params.put(PayConfig.PAY_RESULT_DO_PARAM_BANK, pro.bankInfo());
			params.put(PayConfig.PAY_RESULT_DO_PARAM_CONTENT, pro.toString());// XXX 将pro对象转换成json或者序列化
			
			// 供下个页面获取，展示
			request.setAttribute(PayConfig.PAY_BASE_RESULT_ATTRIBUTE, params);
			PayResultLogicServiceInvoker payResultService = (PayResultLogicServiceInvoker)ctx.getBean("payResultService");
			if (pro.verify()) {// 验证是否成功
				if (pro.success()) {
					
					payResultService.doSuccess(params);
					
					// 如果返回false，则继续采去默认方式进行
					if (!ps.doSuccess(request, response, pro)) {
						if ("".equals(PayConfig.PAY_SUCCESS_URL)) {
							defaultHtml(request, response, pro);
							return;
						}
						post(response, PayConfig.PAY_SUCCESS_URL, params);
					}else{
						defaultHtml(request, response, pro);
						return;
					}
					
				} else {
					payResultService.doFail(params);

					// 如果返回false，则继续采去默认方式进行
					if (!ps.doFail(request, response, pro)) {
						if ("".equals(PayConfig.PAY_FAIL_URL)) {
							defaultHtml(request, response, pro);
							return;
						}
						request.getRequestDispatcher(PayConfig.PAY_FAIL_URL).forward(request, response);
					}else{
						defaultHtml(request, response, pro);
						return;
					}
				}
				
			} else {
				// 验证失败
				// 是否也需要存入？如果需要，同“支付失败”部分

				// 如果返回false，则继续采去默认方式进行
				if (!ps.doVerifyFail(request, response, pro)) {
					if ("".equals(PayConfig.PAY_FAIL_URL)) {
						defaultHtml(request, response, pro);
						return;
					}
					request.getRequestDispatcher(PayConfig.PAY_FAIL_URL).forward(request, response);
				}else{
					defaultHtml(request, response, pro);
					return;
				}
			}

		} catch (Exception e) {
			e.printStackTrace();
			response.sendError(HttpServletResponse.SC_FORBIDDEN);
			return;
		}
	}
	
	private void post(HttpServletResponse response, String url, Map<String, ?> map) throws IOException {
		response.setHeader("Pragma", "No-cache");
		response.setHeader("Cache-Control", "no-cache");
		response.setDateHeader("Expires", 0);
		
		PrintWriter out = response.getWriter();
		
		out.print("<html><body onLoad=\"javascript:document.xxxxxx.submit()\">");
		out.print("<form action=\"");
		out.print(url);
		out.print("\" method=\"post\" name=\"xxxxxx\">");
		
		StringBuffer buffer = new StringBuffer();
		
		
		for (String key : map.keySet()) {
			Object value = map.get(key);
//			if (value instanceof String) {
				buffer.append("<input type=\"hidden\" name=\"")
				.append(key).append("\" value=\"").append(value)
				.append("\">");
//			}
		}
		out.print(buffer.toString());
		out.print("</form></body></html>");
		out.flush();
		out.close();
	}
	
	private void defaultHtml(HttpServletRequest request, HttpServletResponse response, PayResultObject pro) {
		try {
			request.setCharacterEncoding(Constants.DEFAULT_ENCODING);
			response.setCharacterEncoding(Constants.DEFAULT_ENCODING);
			response.setContentType("text/html;charset=" + Constants.DEFAULT_ENCODING);

			// 页面失效
			response.setHeader("Pragma", "No-cache");
			response.setHeader("Cache-Control", "no-cache");
			response.setDateHeader("Expires", 0);
			
			PrintWriter out = response.getWriter();
			
			String s =  new StringBuffer().append(
					"<html><head><title>支付结果</title></head><body>")
					.append("<h1>").append(pro.verify() ? (pro.success() ? "支付成功" : "支付失败") : "支付结果验证失败").append("</h1>")
					.append("<p>订单号：").append(pro.orderId()).append("</p>")
					.append("<p>交易金额：").append(pro.payAmount()).append("</p>")
					.append("<p>银行	：").append(pro.bankInfo()).append("</p>")
					.append("</body></html>")
					.toString();
			
			out.write(s);
			out.flush();
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}

	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		service(request, response);
	}

	protected void doPost(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		service(request, response);
	}

}
